home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Simple Slideshow / TIFF code folder / TIFF.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-20  |  11.8 KB  |  539 lines  |  [TEXT/KAHL]

  1. /* *****************************************************************************
  2.     FILE:             TIFF.c
  3.     
  4.     DESCRIPTION:     routine for reading in TIFF files
  5.  
  6.    ***************************************************************************** */
  7.  
  8.  
  9. #include "TIFF.h"
  10. /*
  11. #include "Error.h"
  12. #include "FileIO.h"
  13. #include "PhotoAlbumUtils.h"
  14. #include "AppGlobals.h"
  15. #include "GrafixUtils.h"
  16. */
  17. #include <Script.h>
  18. #include <Errors.h>
  19. #include <Memory.h>
  20. #include <PictUtil.h>
  21.  
  22. #include    "BitMapUtils.h"
  23.  
  24.  
  25. TIFF_RecHdl        TIFF_Rec_Hdl;
  26. GWorldPtr        display_image_GW;
  27. WindowPtr        display_window;
  28.  
  29.  
  30. static OSErr         CopyToGWorld        ( GWorldPtr gw );
  31.  
  32.  
  33. /************************************************************************
  34. ************************************************************************/
  35.  
  36. GWorldPtr ReadTIFF( FSSpec *spec, short forImage, OSErr *theError, Rect *bounds )
  37. {
  38.     GDHandle         saveDevice;
  39.     GDHandle        mainDevice;
  40.     CGrafPtr         savePort;
  41.     GWorldPtr         myGW, thumb_gw;
  42.     HParamBlockRec    openParams;
  43.     Rect            newRect, tempRect;
  44.     GWorldFlags        myGWorldFlags;
  45.     OSErr            theErr;
  46.     FSSpec            localSpec;
  47.     short            vRefNum, refNum, bit_depth;
  48.     Boolean            OK;
  49.     Str255             temp_str = "\p";
  50.     PixMapHandle    pm;
  51.     
  52.     
  53.     localSpec = *spec;
  54.     vRefNum = localSpec.vRefNum;
  55.     
  56.     /* Set up for the file that we want to use. */        
  57.     openParams.fileParam.ioCompletion = NULL;
  58.     openParams.fileParam.ioNamePtr = localSpec.name;
  59.     openParams.fileParam.ioVRefNum = vRefNum;
  60.     openParams.ioParam.ioVersNum = 0;
  61.     openParams.ioParam.ioPermssn = fsRdPerm;
  62.     openParams.ioParam.ioMisc = NULL;
  63.     openParams.fileParam.ioDirID = localSpec.parID;
  64.     
  65.     theErr = PBHOpenDF( &openParams, FALSE );
  66.     
  67.     if ( ( theErr == fnfErr ) || ( theErr == nsvErr ) )
  68.     {
  69.         *theError = theErr;
  70.         return ( ( GWorldPtr ) NULL );
  71.     }
  72.  
  73.     refNum = openParams.ioParam.ioRefNum;
  74.     
  75.     TIFF_Rec_Hdl = ( TIFF_RecHdl ) NewHandle( ( long ) sizeof( **TIFF_Rec_Hdl ) );
  76.     
  77.     theErr = MemError( );
  78.     OK = (theErr == noErr);    // TO DO: may need an alert here if an error
  79.     
  80.     if ( !OK )
  81.     {
  82.         FSClose( refNum );
  83.         *theError = theErr;
  84.         return ( ( GWorldPtr ) NULL );
  85.     }
  86.     
  87.     ( *TIFF_Rec_Hdl )->ref = -1;
  88.     ( *TIFF_Rec_Hdl )->ti = 0;
  89.     ( *TIFF_Rec_Hdl )->depth = 32;
  90.     ( *TIFF_Rec_Hdl )->dither = FALSE;
  91.     ( *TIFF_Rec_Hdl )->customPalette = TRUE;
  92.     ( *TIFF_Rec_Hdl )->customMethod = systemMethod;
  93.     
  94.     ( *TIFF_Rec_Hdl )->ref = refNum;
  95.         
  96.     ( *TIFF_Rec_Hdl )->ti = ScanTIFF( ( *TIFF_Rec_Hdl )->ref );
  97.         
  98.     if ( ( *TIFF_Rec_Hdl )->ti == 0 || GetTIFFError( ( *TIFF_Rec_Hdl )->ti, temp_str ) != 0 )
  99.     {
  100.         SysBeep(1);    // TO DO: Alert if Error
  101.         DisposeThunk( TIFF_Rec_Hdl );
  102.         return ( ( GWorldPtr ) NULL );
  103.     }
  104.     
  105.     if ( TIFFDrawable( ( *TIFF_Rec_Hdl )->ti ) == FALSE )
  106.     {
  107.         DisposeThunk( TIFF_Rec_Hdl );
  108.         return ( ( GWorldPtr ) NULL );
  109.     }
  110.     
  111.     // eliminate excess depth
  112.     if ( ( *TIFF_Rec_Hdl )->ti->samplesPerPixel == 1 && ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0] < ( *TIFF_Rec_Hdl )->depth )
  113.     {
  114.         ( *TIFF_Rec_Hdl )->depth = FixDepth( ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0] );
  115.     }
  116.         
  117.     newRect.left   = 0;
  118.     newRect.top    = 0;
  119.     newRect.right  = ( *TIFF_Rec_Hdl )->ti->imageWidth;
  120.     newRect.bottom = ( *TIFF_Rec_Hdl )->ti->imageLength;
  121.     
  122.     GetGWorld( &savePort, &saveDevice );
  123.     
  124.  
  125.     theErr = MakeSafeGWorld( &myGW, &newRect, ( *TIFF_Rec_Hdl )->depth, ( *TIFF_Rec_Hdl )->ti->colorMap, TRUE );
  126.  
  127.     SetGWorld( savePort, saveDevice );
  128.     
  129.     if ( theErr == noErr )
  130.     {
  131.         if ( ( theErr = CopyToGWorld( myGW ) ) != noErr )
  132.         {
  133.             if ( GetTIFFError( ( *TIFF_Rec_Hdl )->ti, temp_str ) != 0 && temp_str[0] != 0 )
  134.             {
  135.                 SysBeep(1);    // TO DO: Error Alert
  136.                 DisposeThunk( TIFF_Rec_Hdl );
  137.                 DisposeGWorld( myGW );
  138.                 *theError = theErr;
  139.                 return ( ( GWorldPtr ) NULL );
  140.             }
  141.         }
  142.         
  143.         FSClose( ( *TIFF_Rec_Hdl )->ref );
  144.         ( *TIFF_Rec_Hdl )->ref = -1;
  145.     }
  146.     
  147.     *bounds = newRect;
  148.  
  149.     if ( forImage == FALSE )
  150.     {
  151.         bit_depth  = ( *TIFF_Rec_Hdl )->ti->samplesPerPixel * ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0];
  152.  
  153.         if ( myGW == NULL )
  154.         {
  155.             GetGWorld( &savePort, &saveDevice );
  156.             theErr = MakeSafeGWorld( &myGW, &newRect, 8, ( CTabHandle ) NULL, TRUE );
  157.             SetGWorld( savePort, saveDevice );
  158.             
  159.             theErr = CopyToGWorld( myGW );
  160.         }
  161.  
  162.         newRect = myGW->portRect;
  163.         CalculateThumbNailSize( newRect.right, newRect.bottom, &newRect );
  164.         
  165.         GetGWorld( &savePort, &saveDevice );
  166.         
  167.         theErr = MakeSafeGWorld( &thumb_gw, &newRect,  bit_depth, ( CTabHandle ) NULL, TRUE );
  168.         
  169.  
  170.         SetGWorld( savePort, saveDevice );
  171.         
  172.         if ( theErr == noErr )
  173.         {
  174.             LockPixels( myGW->portPixMap );
  175.             LockPixels( thumb_gw->portPixMap );
  176.             
  177.             GetGWorld( &savePort, &saveDevice );
  178.             SetGWorld( thumb_gw, NULL );
  179.             
  180.             EraseRect( &( thumb_gw->portRect ) );
  181.             CopyBits( ( BitMap * ) &myGW->portPixMap, ( BitMap * ) &thumb_gw->portPixMap,
  182.                         &myGW->portRect, &newRect, ditherCopy, NULL );
  183.                         
  184.             SetGWorld( savePort, saveDevice );
  185.             
  186.             UnlockPixels( myGW->portPixMap );
  187.             UnlockPixels( thumb_gw->portPixMap );
  188.             
  189.             DisposeGWorld( myGW );
  190.             myGW = NULL;
  191.         }
  192.         
  193.         DisposeThunk( TIFF_Rec_Hdl );
  194.         *theError = theErr;
  195.         return ( thumb_gw );
  196.     }
  197.     else
  198.     {
  199.         DisposeThunk( TIFF_Rec_Hdl );
  200.         *theError = noErr;
  201.         return ( myGW );
  202.     }
  203. }
  204.  
  205.  
  206. /************************************************************************
  207. ************************************************************************/
  208.  
  209. static OSErr CopyToGWorld( GWorldPtr gw )
  210. {
  211.     CGrafPtr         oldPort;
  212.     GDHandle         oldGD;
  213.     PixMapHandle     pm;
  214.     OSErr             err;
  215.     Rect             r;
  216.  
  217.  
  218.     GetGWorld( &oldPort, &oldGD );
  219.     SetGWorld( gw, NULL );
  220.     
  221.     pm = GetGWorldPixMap( gw );
  222.     
  223.     if ( LockPixels( pm ) != TRUE )
  224.     {
  225.         SetGWorld( oldPort, oldGD );
  226.         return ( memFullErr );
  227.     }
  228.  
  229.     r = gw->portRect;
  230.     err = DrawTIFF( ( *TIFF_Rec_Hdl )->ref, ( *TIFF_Rec_Hdl )->ti, r, r, ( *TIFF_Rec_Hdl )->dither );
  231.  
  232.     UnlockPixels( pm );
  233.     SetGWorld( oldPort, oldGD );
  234.     
  235.     return ( err );
  236. }
  237.  
  238.  
  239. /************************************************************************
  240. ************************************************************************/
  241.  
  242. void DisposeThunk( TIFF_RecHdl th )
  243. {
  244.     if ( th )
  245.     {
  246.         if ( ( *th )->ti )
  247.         {
  248.             DisposeTIFF( ( *th )->ti );
  249.         }
  250.         
  251.         if ( ( *th )->ref != -1 )
  252.         {
  253.             FSClose( ( *th )->ref );
  254.         }
  255.         
  256.         if ( display_image_GW )
  257.         {
  258.             DisposeGWorld( display_image_GW );
  259.             display_image_GW = NULL;    
  260.         }
  261.         
  262.         DisposHandle( ( Handle ) th );
  263.         th = NULL;
  264.     }
  265. }
  266.  
  267.  
  268.  
  269. /************************************************************************
  270. ************************************************************************/
  271.  
  272. // •••
  273. // Give the window an appropriate palette. Such a palette should have a separate
  274. // set of colors for each different depth CLUT device the window intersects.
  275. // This is possible using inhibited entries, but would be expensive since it
  276. // would require multiple calls to GetPixMapInfo(). And the palette might have
  277. // to be recomputed whenever the user moves the window onto a different screen
  278. // or changes the depth with the Monitors control panel.
  279. //
  280. // It would be nice if the color sampling methods used by GetPixMapInfo() returned
  281. // a palette with the most important colors first, or with multiple sets of
  282. // inhibited colors; such a palette would be useful at multiple depths.
  283. //
  284. // This routine computes a palette for the deepest CLUT device existing at the
  285. // time the TIFF window was created. This isn't perfect; the user might put
  286. // the window on a shallower screen, or change the depth.
  287. //
  288. // InitPalette the color map in the TIFF file if it can. Otherwise it uses the
  289. // Picture Utilities. The sampling method cpmt resource number can be set with
  290. // the 5th argument to TIFFWindow.
  291. // •••
  292.  
  293. void InitPalette( )
  294. {
  295.     CTabHandle             cth;
  296.     PaletteHandle         pltt = 0, opltt;
  297.     PictInfo             pi;
  298.     PixMapHandle         pm;
  299.     OSErr                 err;
  300.     short                 deepest, size;
  301.  
  302.  
  303.     if ( display_image_GW != NULL )
  304.     {
  305.         return;
  306.     }
  307.     
  308.     deepest = DeepestCLUTScreen( );
  309.     size = DepthToSize( deepest );
  310.     
  311.     // Don't bother if there are no color CLUT screens.
  312.     if ( deepest <= 1 )
  313.     {
  314.         return;
  315.     }
  316.     
  317.     if ( ( cth = ( *TIFF_Rec_Hdl )->ti->colorMap ) && ( ( *cth )->ctSize + 1 ) <= size )
  318.     {
  319.         // Use the color map in the TIFF file if it isn't too large.
  320.         pltt = NewPalette( ( *cth )->ctSize + 1, cth, pmTolerant, 0 );
  321.     } 
  322.     else
  323.     if ( ( ( *TIFF_Rec_Hdl)->ti->samplesPerPixel > 1 || ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0] > 1) && ( *TIFF_Rec_Hdl )->customPalette && display_image_GW )
  324.     {
  325.         pm = GetGWorldPixMap( display_image_GW );
  326.         
  327.         if ( LockPixels( pm ) == TRUE )
  328.         {
  329.             err = GetPixMapInfo( pm, &pi, returnPalette | suppressBlackAndWhite, size - 2, ( *TIFF_Rec_Hdl )->customMethod, 0 );
  330.             
  331.             if ( err == noErr )
  332.             {
  333.                 pltt = pi.thePalette;
  334.                 pi.thePalette = 0;
  335.             }
  336.             
  337.             UnlockPixels( pm );
  338.         }
  339.     }
  340.     
  341.     if ( pltt )
  342.     {
  343.         SetPalette( display_window, pltt, TRUE );
  344.     }
  345. }
  346.  
  347.  
  348. /************************************************************************
  349. ************************************************************************/
  350.  
  351. // •••
  352. // Return the depth of the deepest CLUT screen, or zero if there are no
  353. // CLUT screens.
  354. // •••
  355. short DeepestCLUTScreen( )
  356. {
  357.     GDHandle         gd;
  358.     short             depth = 0;
  359.     PixMapHandle     pm;
  360.     
  361.     
  362.     gd = GetDeviceList( );
  363.     
  364.     while ( gd )
  365.     {
  366.         if ( TestDeviceAttribute( gd, screenDevice ) == TRUE && TestDeviceAttribute( gd, screenActive ) == TRUE && ( *gd )->gdType == 0 )
  367.         {
  368.             pm = ( *gd )->gdPMap;
  369.             
  370.             if ( pm && ( *pm )->cmpCount == 1 && ( *pm )->cmpSize > depth )
  371.             {
  372.                 depth = ( *pm )->cmpSize;
  373.             }
  374.         }
  375.         
  376.         gd = GetNextDevice( gd );
  377.     }
  378.     
  379.     return ( depth );
  380. }
  381.  
  382.  
  383. /************************************************************************
  384. ************************************************************************/
  385.  
  386. short DepthToSize( short depth )
  387. {
  388.     switch ( depth )
  389.     {
  390.         case 1:
  391.             return ( 2 );
  392.             break;
  393.             
  394.         case 2:
  395.             return ( 4 );
  396.             break;
  397.             
  398.         case 4:
  399.             return ( 16 );
  400.             break;
  401.             
  402.         default:
  403.             return ( 256 );
  404.     }
  405. }
  406.  
  407.  
  408. /************************************************************************
  409. ************************************************************************/
  410.  
  411. // •••
  412. // Take whatever depth the user provided and round it up to the nearest
  413. // legal QuickDraw depth.
  414. // •••
  415. short FixDepth( short depth )
  416. {
  417.     if ( depth < 1 )
  418.     {
  419.         return ( 0 );
  420.     }
  421.         
  422.     if ( depth <= 1 )
  423.     {
  424.         return ( 1 );
  425.     }
  426.         
  427.     if ( depth <= 2 )
  428.     {
  429.         return ( 2 );
  430.     }
  431.         
  432.     if ( depth <= 4 )
  433.     {
  434.         return ( 4 );
  435.     }
  436.         
  437.     if ( depth <= 8 )
  438.     {
  439.         return ( 8 );
  440.     }
  441.         
  442.     if ( depth <= 16 )
  443.     {
  444.         return ( 16 );
  445.     }
  446.         
  447.     return ( 32 );
  448. }
  449.  
  450.  
  451.  
  452.  
  453.  
  454. /************************************************************************
  455. ************************************************************************/
  456.  
  457. double CalculateThumbNailSize( double old_wide, double old_high, Rect *new_size )
  458. {
  459.     short        new_wide, new_high;
  460.     double        ratio;
  461.     
  462.     
  463.     if ( old_wide > old_high )
  464.     {
  465.         ratio = old_wide / THUMB_SIZE;
  466.         new_wide = THUMB_SIZE;
  467.         new_high = old_high / ratio;
  468.     }
  469.     else
  470.     if ( old_high > old_wide )
  471.     {
  472.         ratio = old_high / THUMB_SIZE;
  473.         new_high = THUMB_SIZE;
  474.         new_wide = old_wide / ratio;
  475.     }
  476.     else
  477.     if ( old_wide < THUMB_SIZE )
  478.     {
  479.         new_high = old_high;
  480.         new_wide = old_wide;
  481.     }
  482.     else
  483.     if ( old_high < THUMB_SIZE )
  484.     {
  485.         new_high = old_high;
  486.         new_wide = old_wide;
  487.     }
  488.     else
  489.     {
  490.         new_high = THUMB_SIZE;
  491.         new_wide = THUMB_SIZE;
  492.     }
  493.     
  494.     SetRect( new_size, 0, 0, new_wide, new_high );
  495.     
  496.     return ( ratio );
  497. }
  498.  
  499.  
  500. //*********************************************************************************
  501.  
  502. // This code added to support create preview in file dialog
  503.  
  504. OSErr    ConvertTIFFToPICT(FSSpec *theFile,PicHandle *thePicture)
  505. {
  506.     OSErr            theErr;
  507.     GWorldPtr        tiffWorld;
  508.     Rect            bounds;    
  509.     PicHandle        temp;
  510.     CGrafPtr        savePort;
  511.     GDHandle        saveDevice;
  512.     PixMapHandle    tiffPix;
  513.     
  514.     tiffWorld = ReadTIFF(theFile,TRUE,&theErr,&bounds);
  515.     
  516.     if ((theErr == noErr) && tiffWorld)
  517.     {
  518.         bounds = tiffWorld->portRect;
  519.         GetGWorld(&savePort,&saveDevice);
  520.         SetGWorld(tiffWorld,NULL);
  521.         
  522.         tiffPix = GetGWorldPixMap(tiffWorld);
  523.         
  524.         if (LockPixels(tiffPix))
  525.         {
  526.             temp = OpenPicture(&bounds);
  527.             ClipRect(&bounds);
  528.             CopyBits((BitMap*)*tiffPix,(BitMap*)*tiffPix,&bounds,&bounds,srcCopy,NULL);
  529.             UnlockPixels(tiffPix);
  530.             ClosePicture();
  531.         }
  532.         
  533.         SetGWorld(savePort,saveDevice);
  534.         DisposeGWorld(tiffWorld);
  535.         
  536.         *thePicture = temp;
  537.     }
  538.     return(theErr);
  539. }